#include "mcurses.h"
#include "console.h"
#include "mstring.h"
#include "ansi.h"

/**
 * @param: void
 * get the size of terminal window
 * @return: void
 * @note: terminal return the size information, format is \033[<lines>;<column>R
 *        sample: \033[20;199R
 */
void mx_mcurses_windsize ()
{
    /* save position, move max, get position, restore position */
    console("%s", ANSI_CSI_SCP ANSI_CSI_CUP(999, 999) ANSI_CSI_DSR ANSI_CSI_RCP);
}

void mx_mcurses_move (mx_mcurses_direction dir, mx_size_t cnt)
{
    switch (dir)
    {
    case MX_MCURSES_DIRECTION_UP:
        if (cnt > 1)
        {
            console(ANSI_CSI_CUU(%u), cnt);
        }
        else if (cnt == 1)
        {
            console_puts(ANSI_CSI_CUU());
        }
        else
        {
            /* reserved */
        }
        break;
    case MX_MCURSES_DIRECTION_DOWN:
        if (cnt > 1)
        {
            console(ANSI_CSI_CUD(%u), cnt);
        }
        else if (cnt == 1)
        {
            console_puts(ANSI_CSI_CUD());
        }
        else
        {
            /* reserved */
        }
        break;
    case MX_MCURSES_DIRECTION_LEFT:
        if (cnt > 1)
        {
            console(ANSI_CSI_CUB(%u), cnt);
        }
        else if (cnt == 1)
        {
            console_puts(ANSI_CSI_CUB());
        }
        else if (cnt == MX_MCURSES_TOEND)
        {
            console_puts(ANSI_C0_CR);
        }
        break;
    case MX_MCURSES_DIRECTION_RIGHT:
        if (cnt > 1)
        {
            console(ANSI_CSI_CUF(%u), cnt);
        }
        else if (cnt == 1)
        {
            console_puts(ANSI_CSI_CUF());
        }
        else
        {
            /* reserved */
        }
        break;
    }
}

void mx_mcurses_goto (mx_usize_t line, mx_usize_t col)
{
}

void mx_mcurses_delete (mx_mcurses_direction dir, mx_size_t cnt)
{
    switch (dir)
    {
    case MX_MCURSES_DIRECTION_LEFT:
        if (cnt > 1)
        {
            /* (<-) (delete) */
            console(ANSI_CSI_CUB(%u) ANSI_CSI_DCH(%u), cnt, cnt);
        }
        else if (cnt == 1)
        {
            console_puts(ANSI_CSI_CUB() ANSI_CSI_DCH());
        }
        else if (cnt == MX_MCURSES_TOEND)
        {
            console_puts(ANSI_CSI_ED(1));
        }
        break;
    case MX_MCURSES_DIRECTION_RIGHT:
        if (cnt > 1)
        {
            /* (<-) (delete) */
            console(ANSI_CSI_CUF(%u) ANSI_CSI_DCH(%u), cnt, cnt);
        }
        else if (cnt == 1)
        {
            console_puts(ANSI_CSI_CUF() ANSI_CSI_DCH());
        }
        else if (cnt == MX_MCURSES_TOEND)
        {
            console_puts(ANSI_CSI_ED(0));
        }
        break;
    }
}

/**
 * insert string in current position
 * @param str: target string to be insert
 * @param after: the string follows the insert position
 * @note: the parameter of `after` doesn't have to be used
 */
void mx_mcurses_insert (mx_string_pt str, mx_string_pt after)
{
    mx_mcurses_delete(MX_MCURSES_DIRECTION_RIGHT, MX_MCURSES_TOEND);
    console_puts(str);
    console_puts(after);
}

void mx_mcurses_insertc (char c, mx_string_pt after)
{
    mx_mcurses_delete(MX_MCURSES_DIRECTION_RIGHT, MX_MCURSES_TOEND);
    console("%c%s", c, after);
    mx_mcurses_move(MX_MCURSES_DIRECTION_LEFT, mx_strlen(after));
}

/**
 * clear line
 * @param: void
 * @return: void
 */
void mx_mcurses_clearline ()
{
    /* line HOME */
    mx_mcurses_move(MX_MCURSES_DIRECTION_LEFT, MX_MCURSES_TOEND);
    /* delete right */
    mx_mcurses_delete(MX_MCURSES_DIRECTION_RIGHT, MX_MCURSES_TOEND);
}

void mx_mcurses_clear ()
{
    console_puts(ANSI_CSI_ED(2));
}

void mx_mcurses_newline (void)
{
    console_puts(ENDL);
}
